﻿using System;
using System.Collections.Generic;
using Common.Library;
using Common.Model;
using Container.Library;
using Dapper.Library;
using DevOps.Model;
using Document.Library;
using Serialize.Library;
using Service.Library;

/*
* 命名空间:DevOps.Logic
*
* 功 能： 服务管理逻辑类
*
* 类 名： SafeServiceInfoImpl
*
* Version   变更日期            负责人     变更内容
* ─────────────────────────────────────────────────
* V1.0.1    2020/05/09 14:34:43 Harvey     创建
*
* Copyright (c) 2020 Harvey Corporation. All rights reserved.
*/

namespace DevOps.Logic
{
    /// <summary>
    /// 接口访问监控日志逻辑类
    /// </summary>
    public class SafeServiceInfoImpl : OperationLogicImpl, ISafeServiceInfoService
    {

        #region 服务基础信息管理

        #region 查询

        /// <summary>
        /// 根据IP地址，服务名称，端口号信息获取服务分页列表信息
        /// </summary>
        /// <param name="inputInfo"></param>
        /// <returns></returns>
        public ResultJsonInfo<List<ServiceInfoResponse>> LoadPageList(ParametersInfo<ServiceInfoQueryRequest> inputInfo)
        {
            var resultInfo = new ResultJsonInfo<List<ServiceInfoResponse>>();

            using (var con = DataBase.GetConnection(DatabaseName.Sql_BUS_DB.ToString()))
            {
                var result = con.QuerySet<SafeServiceInfoEntity>();

                if (inputInfo.parameters.ip.IsNotNullOrEmpty())
                {
                    result.Where(a => a.ip.Contains(inputInfo.parameters.ip));
                }
                if (inputInfo.parameters.port.IsNotNullOrEmpty())
                {
                    result.Where(a => a.port.Equals(inputInfo.parameters.port));
                }
                if (inputInfo.parameters.service_name.IsNotNullOrEmpty())
                {
                    result.Where(a => a.name.Contains(inputInfo.parameters.service_name) || a.display_name.Contains(inputInfo.parameters.service_name));
                }

                #region 排序
                if (inputInfo.field.IsNullOrEmpty())
                {
                    inputInfo.field = " ip";
                }
                if (inputInfo.order.IsNullOrEmpty())
                {
                    inputInfo.order = " asc";
                }
                if (inputInfo.order.ToLower() == "asc")
                {
                    result.OrderBy(inputInfo.field + ",port");
                }
                else
                {
                    result.OrderByDescing(inputInfo.field);
                }
                #endregion

                var listInfo = result.PageList(inputInfo.page, inputInfo.limit);

                if (listInfo.Items.Count > 0)
                {
                    resultInfo.Code = ActionCodes.Success;
                    resultInfo.Data = listInfo.Items.MapToList<ServiceInfoResponse>();
                    resultInfo.Count = listInfo.Total;
                }
                else
                {
                    resultInfo.Data = new List<ServiceInfoResponse>();
                    resultInfo.Msg = "无对应信息！";
                }
            }
            return resultInfo;
        }

        #endregion

        #region 更新功能
        /// <summary>
        /// 更新服务信息
        /// </summary>
        /// <param name="serviceInfo"></param>
        /// <returns></returns>
        public ResultJsonInfo<int> OperateService(ServiceInfoModifyRequest serviceInfo)
        {

            var resultInfo = new ResultJsonInfo<int>();

            using (var con = DataBase.GetConnection(DatabaseName.Sql_BUS_DB.ToString()))
            {
                var user = GetLoginUserInfo();
                //增加 
                if (serviceInfo.id.IsNullOrEmpty())
                {
                    var safeServiceCount = con.QuerySet<SafeServiceInfoEntity>().Where(p => p.ip.Equals(serviceInfo.ip) && p.name.Equals(serviceInfo.name)).Count();
                    if (safeServiceCount == 0)
                    {
                        var safeServiceInfofo = serviceInfo.MapTo<SafeServiceInfoEntity>();
                        safeServiceInfofo.id = GuidHelper.GetGuid();
                        safeServiceInfofo.status = (int)ServiceStatus.Stateless;

                        var result = con.CommandSet<SafeServiceInfoEntity>().Insert(safeServiceInfofo);
                        if (result > 0)
                        {
                            resultInfo.Code = ActionCodes.Success;
                            resultInfo.Msg = "添加成功！";
                            AddOperationLog(OperationLogType.AddOperation, BusinessTitleType.ServiceManage, $"添加了一个新的服务程序，新增信息：{JsonHelper.ToJson(serviceInfo)}");
                        }
                        else
                        {
                            resultInfo.Code = ActionCodes.InvalidOperation;
                            resultInfo.Msg = "添加失败！";
                        }
                    }
                    else
                    {
                        resultInfo.Code = ActionCodes.InvalidOperation;
                        resultInfo.Msg = "添加失败，请确保名称和IP的组合是唯一的！";
                    }
                }
                //修改
                else
                {
                    var safeServiceCount = con.QuerySet<SafeServiceInfoEntity>().Where(p =>p.name.Equals(serviceInfo.name) && !p.id.Equals(serviceInfo.id)).Count();
                    if (safeServiceCount == 0)
                    {

                        var safeServiceInfofo = serviceInfo.MapTo<SafeServiceInfoEntity>();
                        var originalInfo = con.QuerySet<SafeServiceInfoEntity>().Where(p => p.id.Equals(serviceInfo.id)).Get();
                        safeServiceInfofo.status = originalInfo.status;

                        var result = con.CommandSet<SafeServiceInfoEntity>().Update(safeServiceInfofo);
                        if (result > 0)
                        {
                            resultInfo.Code = ActionCodes.Success;
                            resultInfo.Msg = "修改成功！";
                            AddOperationLog(OperationLogType.ModifyOperation, BusinessTitleType.ServiceManage, $"修改了一个服务程序信息，修改信息：{JsonHelper.ToJson(serviceInfo)}");
                        }
                        else
                        {
                            resultInfo.Code = ActionCodes.InvalidOperation;
                            resultInfo.Msg = "修改失败！";
                        }
                    }
                    else
                    {
                        resultInfo.Code = ActionCodes.InvalidOperation;
                        resultInfo.Msg = "修改失败，请确保名称和IP的组合是唯一的！";
                    }
                }
            }
            return resultInfo;
        }

        /// <summary>
        /// 物理删除消息
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public ResultJsonInfo<int> Remove(List<string> ids)
        {
            var resultInfo = new ResultJsonInfo<int>();
            using (var con = DataBase.GetConnection(DatabaseName.Sql_BUS_DB.ToString()))
            {
                //删除
                var result = con.CommandSet<SafeServiceInfoEntity>().Where(p => p.id.In(ids.ToArray())).Delete();
                if (result > 0)
                {
                    resultInfo.Code = ActionCodes.Success;
                    resultInfo.Msg = "删除成功！";
                    AddOperationLog(OperationLogType.RemoveOperation, BusinessTitleType.MessageManage, $"物理删除成功，物理删除信息：{JsonHelper.ToJson(ids)}");
                }
                else
                {
                    resultInfo.Msg = "删除失败！";
                }
            }
            return resultInfo;
        }

        #region 操作服务信息【10安装、20启动、30停止、40卸载】

        /// <summary>
        /// 操作服务信息 【10安装、20启动、30停止、40卸载】
        /// </summary>
        /// <param name="id"></param>
        /// <param name="type"> 【10安装、20启动、30停止、40卸载】</param>
        /// <returns></returns>
        public ResultJsonInfo<int> ControlService(string id, int type)
        {
            var resultInfo = new ResultJsonInfo<int>();

            using (var con = DataBase.GetConnection(DatabaseName.Sql_BUS_DB.ToString()))
            {
                var user = GetLoginUserInfo();
                var safeServiceInfo = con.QuerySet<SafeServiceInfoEntity>().Where(p => p.id.Equals(id)).Get();

                ServiceResultInfo optResult = new ServiceResultInfo();
                if (safeServiceInfo != null)
                {
                    //判断发布文件是否真的已经存在
                    bool isExists = FileHelper.DirectoryExists(safeServiceInfo.file_path);
                    if (safeServiceInfo.is_upload_file && isExists)
                    {
                        //判断服务 寄宿的宿主类型
                        switch (safeServiceInfo.boarding_mode.ToLower())
                        {
                            case "iis":
                                optResult = IISServiceOpt(safeServiceInfo, type);
                                break;
                            case "windows":
                                optResult = WindowsServiceOpt(safeServiceInfo, type);
                                break;
                        }

                        //操作服务具体操作
                        if (optResult.Success)
                        {
                            var result = 0;
                            switch (type)
                            {
                                case (int)ServiceOperationType.Install:
                                    switch (safeServiceInfo.boarding_mode.ToLower())
                                    {
                                        case "iis":
                                            safeServiceInfo.status = (int)ServiceStatus.Running;
                                            break;
                                        case "windows":
                                            safeServiceInfo.status = (int)ServiceStatus.NotRunning;
                                            break;
                                    }
                                    result = con.CommandSet<SafeServiceInfoEntity>().Update(safeServiceInfo);
                                    resultInfo.Msg = "安装成功！";
                                    break;
                                case (int)ServiceOperationType.Running:
                                    safeServiceInfo.status = (int)ServiceStatus.Running;
                                    result = con.CommandSet<SafeServiceInfoEntity>().Update(safeServiceInfo);
                                    resultInfo.Msg = "启动成功！";
                                    break;
                                case (int)ServiceOperationType.Stop:
                                    safeServiceInfo.status = (int)ServiceStatus.Stop;
                                    result = con.CommandSet<SafeServiceInfoEntity>().Update(safeServiceInfo);
                                    resultInfo.Msg = "停止成功！";
                                    break;
                                case (int)ServiceOperationType.Uninstall:

                                    //卸载了的程序，不要删除掉原有发布包的发布文件
                                    safeServiceInfo.status = (int)ServiceStatus.Uninstalled;
                                    result = con.CommandSet<SafeServiceInfoEntity>().Update(safeServiceInfo);
                                    resultInfo.Msg = "卸载成功！";
                                    break;
                            }

                            if (result > 0)
                            {
                                resultInfo.Code = ActionCodes.Success;
                                AddOperationLog(OperationLogType.ModifyOperation, BusinessTitleType.ServiceManage, $"操作服务程序，服务程序信息：{JsonHelper.ToJson(safeServiceInfo)}");
                            }
                            else
                            {
                                resultInfo.Code = ActionCodes.InvalidOperation;
                                resultInfo.Msg = "操作失败！";
                            }
                        }
                        else
                        {
                            resultInfo.Code = ActionCodes.InvalidOperation;
                            resultInfo.Msg = optResult.Msg;
                        }
                    }
                    else
                    {
                        //发布文件不存在，就将状态还原 
                        safeServiceInfo.status = (int)ServiceStatus.Stateless;
                        safeServiceInfo.is_upload_file = false;
                        var result = con.CommandSet<SafeServiceInfoEntity>().Update(safeServiceInfo);

                        resultInfo.Code = ActionCodes.InvalidOperation;
                        resultInfo.Data = 1;
                        resultInfo.Msg = "发布文件不存在";
                    }
                }
                else
                {
                    resultInfo.Msg = "无对应信息！";
                }
            }
            return resultInfo;
        }

        /// <summary>
        /// IIS服务操作
        /// </summary>
        private ServiceResultInfo IISServiceOpt(SafeServiceInfoEntity safeServiceInfo, int type)
        {
            ServiceResultInfo result = new ServiceResultInfo();

            WebsiteInfo websiteInfo = new WebsiteInfo();
            websiteInfo.AppPool = safeServiceInfo.name;
            websiteInfo.IP = safeServiceInfo.ip;
            websiteInfo.Port = safeServiceInfo.port;
            websiteInfo.DomainPort = safeServiceInfo.ip + ":" + safeServiceInfo.port;
            websiteInfo.SiteName = safeServiceInfo.name;
            websiteInfo.PhysicalPath = safeServiceInfo.file_path;
            websiteInfo.FrameworkVersion = safeServiceInfo.framework_version.GetEnumDescriptionByValue(typeof(FrameworkVersion));
            websiteInfo.HostedMode = safeServiceInfo.hosted_mode == "集成" ? 0 : 1;
            IISWorkerClient workerClient = IISWorkerClient.InitService(websiteInfo);

            switch (type)
            {
                case (int)ServiceOperationType.Install:
                    result = workerClient.CreateWebSite(true);
                    break;
                case (int)ServiceOperationType.Running:
                    result = workerClient.StartWebSite();
                    break;
                case (int)ServiceOperationType.Stop:
                    result = workerClient.StopWebSite();
                    break;
                case (int)ServiceOperationType.Uninstall:
                    result = workerClient.DelSite();
                    break;
            }
            return result;
        }

        /// <summary>
        /// Windows服务操作
        /// </summary>
        /// <param name="safeServiceInfo"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        private ServiceResultInfo WindowsServiceOpt(SafeServiceInfoEntity safeServiceInfo, int type)
        {
            ServiceResultInfo result = new ServiceResultInfo();

            string exeFile = safeServiceInfo.file_path + "\\" + safeServiceInfo.exe_file;

            string domainPort = "http://" + safeServiceInfo.ip + ":" + safeServiceInfo.port;
            string resultStr = string.Empty;

            if (safeServiceInfo.service_type.ToLower() == "windows")
            {
                string InstallUtilFile = safeServiceInfo.file_path + "\\InstallUtil.exe";

                WindowsServiceInfo serviceInfo = new WindowsServiceInfo();

                serviceInfo.IP = safeServiceInfo.ip;
                serviceInfo.Port = safeServiceInfo.port;
                serviceInfo.DomainPort = "http://" + safeServiceInfo.ip + ":" + safeServiceInfo.port;
                serviceInfo.PhysicalPath = safeServiceInfo.file_path;
                serviceInfo.ServiceName = safeServiceInfo.name;
                WindowsWorkerClient workerClient = WindowsWorkerClient.InitService(serviceInfo);

                switch (type)
                {
                    case (int)ServiceOperationType.Install:
                        //resultStr = HttpProtocolHelper.SendGetRequestAsString($"http://{safeServiceInfo.ip}:{safeServiceInfo.servo_port}/Service/Install?serviceFileName={exeFile}");
                        result = ExecuteCMD(InstallUtilFile, exeFile);
                        break;
                    case (int)ServiceOperationType.Running:
                        result = workerClient.RunningService();
                        //resultStr = HttpProtocolHelper.SendGetRequestAsString($"http://{safeServiceInfo.ip}:{safeServiceInfo.servo_port}/Service/Start?serviceFileName={exeFile}&textBoxStartParams={domainPort}");
                        break;
                    case (int)ServiceOperationType.Stop:
                        result = workerClient.StopService();
                        //resultStr = HttpProtocolHelper.SendGetRequestAsString($"http://{safeServiceInfo.ip}:{safeServiceInfo.servo_port}/Service/Stop?serviceFileName={exeFile}");
                        break;
                    case (int)ServiceOperationType.Uninstall:
                        result = ExecuteCMD(InstallUtilFile + "  /u", exeFile);
                        //resultStr = HttpProtocolHelper.SendGetRequestAsString($"http://{safeServiceInfo.ip}:{safeServiceInfo.servo_port}/Service/Uninstall?serviceFileName={exeFile}");
                        break;
                }
                //result = resultStr.JsonToObject<ServiceResultInfo>();

            }
            else
            {
                string cmdStr = string.Empty;
                switch (type)
                {
                    case (int)ServiceOperationType.Install:
                        cmdStr = "Install"; ;
                        break;
                    case (int)ServiceOperationType.Running:
                        cmdStr = "Start"; ;
                        break;
                    case (int)ServiceOperationType.Stop:
                        cmdStr = "Stop"; ;
                        break;
                    case (int)ServiceOperationType.Uninstall:
                        cmdStr = "Uninstall"; ;
                        break;
                }
                result = ExecuteCMD(exeFile, cmdStr);
            }
            return result;
        }

        /// <summary>
        /// 执行CMD命令
        /// </summary>
        /// <param name="exeFile"></param>
        /// <param name="cmd"></param>
        private ServiceResultInfo ExecuteCMD(string exeFile, string cmd)
        {
            ServiceResultInfo result = new ServiceResultInfo();
            try
            {
                System.Diagnostics.Process p = new System.Diagnostics.Process();
                //设置要启动的应用程序
                p.StartInfo.FileName = "cmd.exe";
                //是否使用操作系统shell启动
                p.StartInfo.UseShellExecute = false;
                // 接受来自调用程序的输入信息
                p.StartInfo.RedirectStandardInput = true;
                //输出信息
                p.StartInfo.RedirectStandardOutput = true;
                // 输出错误
                p.StartInfo.RedirectStandardError = true;
                //不显示程序窗口
                p.StartInfo.CreateNoWindow = true;
                //启动程序
                p.Start();
                //向cmd窗口发送输入信息
                p.StandardInput.WriteLine(exeFile + " " + cmd + " &exit");

                p.StandardInput.AutoFlush = true;
                //获取输出信息
                string strOuput = p.StandardOutput.ReadToEnd();
                //等待程序执行完退出进程
                p.WaitForExit();
                p.Close();

                result.Msg = "操作成功！";
            }
            catch (Exception ex)
            {
                result.Msg = ex.Message; ;
            }
            return result;
        }
        #endregion

        /// <summary>
        /// 全面核查
        /// </summary>
        /// <returns></returns>
        public ResultJsonInfo<int> Check()
        {
            var resultInfo = new ResultJsonInfo<int>();
            using (var con = DataBase.GetConnection(DatabaseName.Sql_BUS_DB.ToString()))
            {
                var result = con.QuerySet<SafeServiceInfoEntity>().ToList();
                if (result.Count > 0)
                {
                    ServiceResultInfo serviceResultInfo = new ServiceResultInfo();
                    //轮训所有服务信息, 根据不同的服务类型 IIS/Windows 来做核查操作
                    foreach (var item in result)
                    {
                        //如果是IIS，就使用IIS 帮助类
                        if (item.boarding_mode.ToLower() == "iis")
                        {
                            serviceResultInfo = CheckWebSite(item);
                            if (serviceResultInfo.Success)
                            {
                                switch (serviceResultInfo.Code)
                                {
                                    //不存在
                                    case 0:
                                        if (item.status!=(int)ServiceStatus.Uninstalled)
                                        {
                                            item.status = (int)ServiceStatus.Uninstalled;
                                            con.CommandSet<SafeServiceInfoEntity>().Update(item);
                                        }
                                        break;
                                    //运行中
                                    case 2:
                                        if (item.status != (int)ServiceStatus.Running)
                                        {
                                            item.status = (int)ServiceStatus.Running;
                                            con.CommandSet<SafeServiceInfoEntity>().Update(item);
                                        }
                                        break;
                                    //停止
                                    case 4:
                                        if (item.status != (int)ServiceStatus.Stop)
                                        {
                                            item.status = (int)ServiceStatus.Stop;
                                            con.CommandSet<SafeServiceInfoEntity>().Update(item);
                                        }
                                        break;
                                }

                            }
                        }
                        else
                        {
                            serviceResultInfo = CheckWindowsService(item);
                            if (serviceResultInfo.Success)
                            {
                                switch (serviceResultInfo.Code)
                                {
                                    case 1://服务未运行！
                                        if (item.status != (int)ServiceStatus.NotRunning)
                                        {
                                            item.status = (int)ServiceStatus.NotRunning;
                                            con.CommandSet<SafeServiceInfoEntity>().Update(item);
                                        }
                                        break;
                                    case 2://服务正在启动！
                                    case 4://该服务正在运行！
                                        if (item.status != (int)ServiceStatus.Running)
                                        {
                                            item.status = (int)ServiceStatus.Running;
                                            con.CommandSet<SafeServiceInfoEntity>().Update(item);
                                        }
                                        break;
                                    case 3://服务正在停止！
                                    case 5://服务继续处于挂起状态
                                    case 6://服务暂停处于挂起状态！
                                    case 7://服务已暂停！
                                        if (item.status != (int)ServiceStatus.Stop)
                                        {
                                            item.status = (int)ServiceStatus.Stop;
                                            con.CommandSet<SafeServiceInfoEntity>().Update(item);
                                        }
                                        break;
                                    case 10://指定文件不是Windows服务！
                                    case 11://服务不存在！
                                        if (item.status != (int)ServiceStatus.Uninstalled)
                                        {
                                            item.status = (int)ServiceStatus.Uninstalled;
                                            con.CommandSet<SafeServiceInfoEntity>().Update(item);
                                        }
                                        break;
                                }
                            }
                        }
                    }
                }
                resultInfo.Code = ActionCodes.Success;
                resultInfo.Msg = "核查完毕！";
            }
            return resultInfo;
        }

        /// <summary>
        /// 核查Windows服务
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private ServiceResultInfo CheckWindowsService(SafeServiceInfoEntity item)
        {

            WindowsServiceInfo serviceInfo = new WindowsServiceInfo();
            serviceInfo.IP = item.ip;
            serviceInfo.Port = item.port;
            serviceInfo.DomainPort = "http://" + item.ip + ":" + item.port;
            serviceInfo.PhysicalPath = item.file_path;
            serviceInfo.ServiceName = item.name;
            WindowsWorkerClient workerClient = WindowsWorkerClient.InitService(serviceInfo);

            return workerClient.ViewService();
        }

        /// <summary>
        /// 核查IIS站点
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private ServiceResultInfo CheckWebSite(SafeServiceInfoEntity item)
        {
            WebsiteInfo website = new WebsiteInfo();
            website.IP = item.ip;
            website.Port = item.port;
            website.DomainPort = "http://" + item.ip + ":" + item.port;
            website.PhysicalPath = item.file_path;
            website.SiteName = item.name;
            IISWorkerClient workerClient = IISWorkerClient.InitService(website);
            return workerClient.ViewSiteState();
        }
        #endregion

        #endregion
    }
}
